package com.song.ResourceNode.client;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

import org.apache.commons.collections.CollectionUtils;

import love.cq.util.CollectionUtil;

import com.song.corebean.MessageType;
import com.song.corebean.PackageHead;
import com.song.corebean.PackageMessage;
import com.song.corebean.utils.CoreUtils;

import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.handler.timeout.ReadTimeoutHandler;

public class NodeClient  {
	
	
	public PackageMessage msg;
	

	private EventLoopGroup group ;
	
	private ChannelFuture future;
	
	private NodeClientHandler handler;
	
	public void  connect(final String addr , final int port)
	{
		EventLoopGroup group = new NioEventLoopGroup();
		ExecutorService pool =  Executors.newFixedThreadPool(1);
		this.group = group;
		this.handler = new NodeClientHandler();
		final  Bootstrap bootstrap = new Bootstrap();
		bootstrap.group(group).channel(NioSocketChannel.class)
				.handler(new ChannelInitializer<SocketChannel>() {
					@Override
					protected void initChannel(SocketChannel ch)
							throws Exception {
						ChannelPipeline p = ch.pipeline();
						p.addLast(new ObjectEncoder(), new ObjectDecoder(
								ClassResolvers.cacheDisabled(null)));
						p.addLast(new IdleStateHandler(10,0,0));
						p.addLast(new HeartBeatHandler());
						p.addLast(handler);
					}

				});
		try {
			this.future = bootstrap.connect(addr, port).await();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
//		finally{
//				try {
//					this.future = bootstrap.connect(addr, port).await();
//				} catch (InterruptedException e) {
//					// TODO Auto-generated catch block
//					e.printStackTrace();
//				}
//		}
	}
	
	public void release()
	{
		this.group.shutdownGracefully();
	}
	
	public Object sendAndRecv(MessageType messageType ,String key, Object val)
	{
		try {
			PackageMessage msg = CoreUtils.dataToPackageMessage(messageType, key,val);
			this.future.channel().writeAndFlush(msg).sync() ;
			while(true)
			{
				if(!handler.isEmpQueue())
					break;
			}
			return this.handler.readMsg().body.bundle.get("data");
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	public static void main(String[] args) {
		NodeClient client = new NodeClient();
		client.connect("192.168.2.114", 58000);
		System.out.println(client.sendAndRecv(MessageType.GET_HOSTS,null,null));
		System.out.println(client.sendAndRecv(MessageType.GET_HOSTS,null,null));
	}
}
